<?php

namespace app;


use extend\Upload;

class QCmt
{

    static $page = 1;
    static $user_id = 0;
    static $config;
    static $page_num = 10;

    const MAX_SUBMIT_PER_HOUR = 20; // 每小时最大提交次数
    const MAX_SUBMIT_PER_DAY = 100; // 每天最大提交次数
    const CONTENT_MIN_LENGTH = 2;
    const CONTENT_MAX_LENGTH = 500;

    static function init()
    {
        $data = input();

        $action = $data['qcmt'];

        self::$page = $data['page'] ?? 1;

        if (!self::auth()) {
            return json('非法访问', 0);
        }

        self::$user_id = call_user_func('get_user_id');
        global $comment_config;
        self::$config = $comment_config;

        if (method_exists(QCmt::class, $action)) {
            return call_user_func_array([QCmt::class, $action], [$data]);
        } else {
            return json('', 0, '');
        }
    }


    static function auth()
    {
        $data = input('post.');

        $hash = $data['_'] ?? '';
        if (!$hash) {
            return false;
        }
        unset($data['_'],$data['app'], $data['_h_'], $data['qcmt'], $data['PHPSESSID']);

        $keys = array_keys($data);
        sort($keys);

        $md5 = md5(json_encode($keys));

//        p(json_encode($keys),$md5);

        return $hash == $md5;
    }

    /**
     * 加载评论
     * @auth false
     * @param $params
     */
    static function load($params)
    {

        $limit_start = self::$page * (self::$page_num) - (self::$page_num);
        $limit_end = self::$page * (self::$page_num);

        $data_id = $params['data_id'] ?? 0;
        $type = $params['type'] ?? '';

        $cmt_id = $params['cmt_id'] ?? 0;

        if ($cmt_id) {
            //加载更多回复
            $num = (int)$params['num'];
            $replys = self::getReplys($cmt_id, 1, $num);

            return json($replys);
        }


        if (!$data_id || !$type) {
            return json('初始化失败', 0);
        }

        $DB = db()->where('C.data_id', $data_id)->where('C.type', $type);

        $DB->join(self::$config['user_table'] . ' U', 'U.' . self::$config['user_pk'] . '=C.from_uid', 'left');


        //排序
        $sort = $params['sort'] ?? 'date';
//        $db->orderBy("id","asc");

        switch ($sort) {
            case 'zan':
                $DB->orderBy('zan', 'desc');
                break;
            case 'hot':
                $DB->orderBy('replies', 'desc');
                break;
            default:
                $DB->orderBy('id', 'desc');
        }

        $list = $DB->get(self::$config['table'] . ' C', [$limit_start, $limit_end], [
            'C.*',
            'CASE 
                WHEN C.anms_nickname IS NOT NULL THEN C.anms_nickname 
                ELSE U.' . self::$config['nickname'] . ' 
            END as nickname',
            'CASE 
                WHEN C.anms_avatar IS NOT NULL THEN C.anms_avatar 
                ELSE U.' . self::$config['avatar'] . ' 
            END as avatar'
        ]);

        if ($list) {
            foreach ($list as &$row) {
                $row['replys'] = self::getReplys($row['id'], 1);
            }
        }

        return json($list);
    }


    static function getReplys($cmt_id, $page = 1, $start = 0)
    {
        $config = self::$config;

        $start = $start + $page * (3) - (3);

        $end = $start + $page * (3);


        $limit = " limit {$start},{$end} ";

        $sql = "SELECT 
            R.id, R.cmt_id, R.from_uid, R.to_uid, R.content, R.zan, R.cai, R.time, R.ip, R.replies,
            CASE 
                WHEN R.anms_nickname IS NOT NULL THEN R.anms_nickname 
                ELSE FU.{$config['nickname']} 
            END as from_nickname,
            CASE 
                WHEN R.anms_avatar IS NOT NULL THEN R.anms_avatar 
                ELSE FU.{$config['avatar']} 
            END as from_avatar,
            CASE 
                WHEN R.anms_nickname IS NOT NULL THEN R.anms_nickname 
                ELSE TU.{$config['nickname']} 
            END as to_nickname,
            CASE 
                WHEN R.anms_avatar IS NOT NULL THEN R.anms_avatar 
                ELSE TU.{$config['avatar']} 
            END as to_avatar
            FROM {$config['reply_table']} R 
            LEFT JOIN {$config['user_table']} FU ON R.from_uid = FU.id 
            LEFT JOIN {$config['user_table']} TU ON R.to_uid = TU.{$config['user_pk']} 
            WHERE cmt_id = {$cmt_id} AND R.status = 1 
            ORDER BY zan DESC, id DESC {$limit}";


        return db()->rawQuery($sql);
    }

    /**
     * 文件上传
     * @auth false
     * @param $params
     */
    static function upload($params)
    {

        $Uploader = new Upload();

        if (!isset($params['blob']) || !$params['blob']) {
            return json('');
        }

        if (!self::$user_id) {
            return json('请先登录', 0);
        }

        $dir = $params['type'] != 'image' ? 'comments/files' : 'comments/images';

        $file_name = $params['name'] ?? '';

        $res = $Uploader->saveRawFile($params['blob'], $dir, '', $params['type'] != 'image' ? 'mp3' : 'jpg', $file_name);

        return json($res);
    }


    /**
     * 赞踩操作
     * @auth false
     * @param $params
     * @return string
     */
    static function action($params)
    {

        $action = $params['cmtAction'];

        $id = (int)$params['id'];

        $table = (isset($params['type']) && $params['type'] == 'reply') ? self::$config['reply_table'] : self::$config['table'];

        $data = '';

        $params['action_uid'] = self::$user_id;

        switch ($action) {
            case 'zan':
                $data = self::setNum($table, $id, 'zan', $params);
                break;
            case 'cai':
                $data = self::setNum($table, $id, 'cai', $params);
                break;
        }


        return json($data, 200, '');
    }


    static function getWhere($table, $id, $field)
    {
        $DB = db()->where('uid', self::$user_id)->where('action', $field)->where('type', 'comment');
        if ($table == self::$config['reply_table']) {
            $DB->where('reply_id', $id);
        } else {
            $DB->where('data_id', $id);
        }
        return $DB;
    }

    protected static function setNum($table, $id, $field, $params)
    {

        $row = db()->where('id', $id)->getOne($table);
        $num = (int)$row[$field];

        //记录赞踩行为

        $DB = self::getWhere($table, $id, $field);

        $has = $DB->getOne(self::$config['action_table']);

        if (!$has) {
            $insert = ['uid' => self::$user_id, 'type' => 'comment', 'action' => $field, 'ip' => _ip_()];
            if ($table == self::$config['table']) {
                $insert['data_id'] = $id;
            } else {
                $insert['reply_id'] = $id;
                $insert['data_id'] = $row['cmt_id'];
            }
            $DB->insert(self::$config['action_table'], $insert);

            $num += 1;

            if (is_callable(self::$config['action_callback'])) {
                call_user_func(self::$config['action_callback'], $params);
            }
        } else {
            self::getWhere($table, $id, $field)->delete(self::$config['action_table']);
            $num -= 1;
        }


        db()->where('id', $id)->update($table, [$field => $num]);

        return $num;
    }

    protected static function checkSubmitFrequency($user_id, $ip) {
        $hour_ago = date('Y-m-d H:i:s', strtotime('-1 hour'));
        $day_ago = date('Y-m-d H:i:s', strtotime('-24 hours'));
        
        // 检查小时提交次数
        $hour_count = db()->where('from_uid', $user_id)
            ->where('ip', $ip)
            ->where('time >= ?', [$hour_ago])
            ->get(self::$config['table'], null, 'COUNT(*) as count')[0]['count'];
            
        if($hour_count >= self::MAX_SUBMIT_PER_HOUR) {
            return json('发布太频繁，请稍后再试', 0);
        }
        
        // 检查天提交次数
        $day_count = db()->where('from_uid', $user_id)
            ->where('ip', $ip)
            ->where('time >= ?', [$day_ago])
            ->get(self::$config['table'], null, 'COUNT(*) as count')[0]['count'];
            
        if($day_count >= self::MAX_SUBMIT_PER_DAY) {
            return json('今日评论次数已达上限', 0);
        }
        
        return true;
    }
    
    protected static function checkContent($content, $files) {
        // 检查内容长度
        $content_length = mb_strlen(trim($content));
        if($content_length < self::CONTENT_MIN_LENGTH && empty($files)) {
            return json('评论内容太短', 0);
        }
        
        if($content_length > self::CONTENT_MAX_LENGTH) {
            return json('评论内容超出长度限制', 0);
        }
        
        // 敏感词过滤
        $sensitive_words = ['spam', 'ad', '广告']; // 可以配置更多敏感词
        foreach($sensitive_words as $word) {
            if(stripos($content, $word) !== false) {
                return json('评论内容包含敏感词', 0);
            }
        }
        
        return true;
    }

    static function sumbit($params)
    {
        $config = self::$config;

        if (!self::$user_id) {
            return json('请先登录', 0);
        }

        if (!isset($params['data_id']) || !$params['data_id']) {
            return json('非法提交', 0);
        }

        // 检查提交频率
        $check_frequency = self::checkSubmitFrequency(self::$user_id, _ip_());
        if($check_frequency !== true) {
            return $check_frequency;
        }

        $insert_table = (isset($params['at']['type'])) ? self::$config['reply_table'] : self::$config['table'];

        $content = isset($params['content']) ? htmlspecialchars($params['content']) : '';
        $files = isset($params['files']) ? $params['files'] : [];

        // 检查内容
        $check_content = self::checkContent($content, $files);
        if($check_content !== true) {
            return $check_content;
        }

        $data = [
            'from_uid' => self::$user_id,
            'content' => $content,
            'ip' => _ip_(),
            'status' => self::$config['cmt_default_status'],
            'files' => ($params['files'] && is_array($params['files'])) ? json_encode($params['files']) : ''
        ];

        // 添加匿名用户信息
        if (isset($params['anonymous'])) {
            $data['anms_nickname'] = htmlspecialchars($params['anonymous']['nickname']);
            $data['anms_avatar'] = str_replace('./', '', $params['anonymous']['avatar']);
            if(!empty($params['anonymous']['email'])) {
                $data['anms_email'] = filter_var($params['anonymous']['email'], FILTER_SANITIZE_EMAIL);
            }
        }

        if (!$data['content'] && !$data['files']) {
            return json('评论为空', 0);
        }

        if ((isset($params['at']['type']))) {
            //回复留言还是回复回复
            $cmt_target = $params['at']['type'];

            //这里是回复
            $id = (int)$params['at']['id'];

            $target = db()->where('id', $id)->getOne($cmt_target == 'comment' ? self::$config['table'] : self::$config['reply_table']);


            $data['to_uid'] = $target['from_uid'];
            $data['cmt_id'] = $target['cmt_id'] ?? $target['id'];
            $data['reference'] = $cmt_target == 'reply' ? $target['id'] : 0;
        } else {
            $data['data_id'] = (int)$params['data_id'];
            $data['type'] = $params['type'];
        }
      
        $DB = db();

        $DB->insert($insert_table, $data);
        $id = $DB->getInsertId();

        if ($id) {
            $data['type']=$params['type'];
            $data['id']=$id;
            if (is_callable(self::$config['comment_callback'])) {
                call_user_func(self::$config['comment_callback'], $data);
            }
        }

        if (isset($data['cmt_id'])) {
            //更新评论数目
            $sql = "update {$config['table']} C left join (select cmt_id,count(1) as num from {$config['reply_table']} where cmt_id={$data['cmt_id']} group by cmt_id) T on C.id=T.cmt_id set C.replies=T.num where C.id={$data['cmt_id']}";

            db()->rawQuery($sql);

            if (isset($data['reference'])) {
                //更新引用
                $sql = "update {$config['reply_table']} Q left join  (select count(1) as num,reference from {$config['reply_table']} where reference = {$data['reference']} group by reference) T on Q.id=T.reference set Q.replies=T.num where Q.id={$data['reference']}";

                db()->rawQuery($sql);
            }
        }

        if (isset($params['at']['type'])) {
            // 获取被回复的评论/回复
            $target_table = $params['at']['type'] == 'comment' ? self::$config['table'] : self::$config['reply_table'];
            $target = db()->where('id', $params['at']['id'])->getOne($target_table);
            
            // 如果存在匿名邮箱,发送通知
            if(!empty($target['anms_email'])) {
                self::sendNotificationEmail(
                    $target['anms_email'],
                    $target['content'],
                    $data['content']
                );
            }
        }

        if (!isset($params['at']['type'])) {
            //这里是评论
            $sql = "select C.id,from_uid,content,zan,cai,time,ip,replies,files,
                    COALESCE(C.anms_nickname, U.{$config['nickname']}) as nickname,
                    COALESCE(C.anms_avatar, U.{$config['avatar']}) as avatar 
                    from {$config['table']} C 
                    left join {$config['user_table']} U on C.from_uid=U.{$config['user_pk']} 
                    where C.id={$id}";

            $cmt = db()->rawQuery($sql);

        } else {
            //这里是子回复
            $sql = "select R.id,cmt_id,from_uid,to_uid,content,zan,cai,time,ip,replies,
                    COALESCE(R.anms_nickname, FU.{$config['nickname']}) as from_nickname,
                    COALESCE(R.anms_avatar, FU.{$config['avatar']}) as from_avatar,
                    COALESCE(R.anms_nickname, TU.{$config['nickname']}) as to_nickname,
                    COALESCE(R.anms_avatar, TU.{$config['avatar']}) as to_avatar 
                    from {$config['reply_table']} R 
                    left join {$config['user_table']} FU on R.from_uid=FU.id 
                    left join {$config['user_table']} TU on R.to_uid=TU.{$config['user_pk']} 
                    where R.id={$id}";

            $cmt = db()->rawQuery($sql);
        }


        return json(['cmt' => $cmt, 'type' => isset($params['at']['type']) ? 'reply' : 'comment'], 200, '');

    }

    // 添加邮件通知方法
    protected static function sendNotificationEmail($to_email, $content, $reply_content) {
        if(empty($to_email)) return;
        
        $subject = '您的评论收到了新回复';
        $message = "
            <h3>您的评论收到了新回复</h3>
            <p>您的评论: {$content}</p>
            <p>回复内容: {$reply_content}</p>
            <hr>
            <p style='color:#999;font-size:12px;'>本邮件由系统自动发送,请勿回复</p>
        ";
        
        $headers = "MIME-Version: 1.0\r\n";
        $headers .= "Content-type: text/html; charset=utf-8\r\n";
        $headers .= "From: no-reply@" . $_SERVER['HTTP_HOST'] . "\r\n";
        
        mail($to_email, $subject, $message, $headers);
    }
}